package com.swa99ylum.pxf;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.swa99ylum.pxf.sheet.SheetFiller;

public class PluggableXSSFFiller {
	
	private static Logger logger = Logger.getLogger(PluggableXSSFFiller.class);
	
	private XSSFWorkbook workbook;
	private SheetFiller[] sheetFillers;
	
	
	/*--------------------------------------------
    |      			1 个  构造器			         |
    ============================================*/
	/**
	 * 构造器
	 */
	public PluggableXSSFFiller(XSSFWorkbook workbook, XSSFSheet styleSheet, SheetFiller[] sheetFillers) {
		super();
		this.workbook = workbook;
		this.sheetFillers = sheetFillers;
		
		if(styleSheet != null) spreadStyleMap(initStyleMap(styleSheet));
	}
	
	public PluggableXSSFFiller(XSSFWorkbook workbook, SheetFiller[] sheetFillers) {
		this(workbook, null, sheetFillers);
	}
	
	public PluggableXSSFFiller(XSSFWorkbook workbook, SheetFiller[] sheetFillers, String styleSheetName) {
		this(workbook, workbook.getSheet(styleSheetName), sheetFillers);
	}
	
	public PluggableXSSFFiller(XSSFWorkbook workbook, SheetFiller[] sheetFillers, int styleSheetIndex) {
		this(workbook, workbook.getSheetAt(styleSheetIndex), sheetFillers);
	}
	
	
	
	/**
	 * styleMap 构造器：
	 * key：sheet 中的 所有 cell
	 * value：每个 cell 的 style
	 */
	/** public */ private Map<String, XSSFCellStyle> initStyleMap(XSSFSheet sheet) {
		
		Map<String, XSSFCellStyle> styleMap = new HashMap<String, XSSFCellStyle>();
		
		//遍历 row
		for(int i=sheet.getFirstRowNum(); i<=sheet.getLastRowNum(); i++) {
			
			XSSFRow row = sheet.getRow(i);
			
			if(row != null) {
				
				//遍历 cell
				for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {
					
					XSSFCell cell = row.getCell(j);
					
					if(cell != null) {
						styleMap.put(cell.getAddress().toString(), cell.getCellStyle());
					}
					
				}
			}
		}
		
		/*
		for (Entry<String, XSSFCellStyle> entry : styleMap.entrySet()) {
			System.out.println(entry.getKey() + " <=> " + entry.getValue());
		}
		*/
		
		return styleMap;
	}

	
	/**
	 * 对于 xlsx 的 
	 * "读操作"(pxp)：是一个 由 用户发起的事件(用户在页面上传文件)，开发者 和用户约定 xlsx 的解析规则，开发者再用 java代码解析、检查 用户上传的 xlsx，
	 * 				当发现 上传的文件中，有违反 双方约定 的 数据、格式 时，就要进行"错误收集"
	 * "写操作"(pxf)：是一个 由 开发者 主观发起的 意图，不需要进行"错误收集"
	 */
//	//pxf 不需要进行 错误收集
//	public void spreadErrorHook(List<String> errors) {
//		...
//	};
	
	/**
	 * 将 styleMap 传播到 各个 cellInjector.style 中
	 */
	public void spreadStyleMap(Map<String, XSSFCellStyle> styleMap) {
		for (SheetFiller sheetFiller : sheetFillers) {
			sheetFiller.spreadStyleMap(styleMap);
		}
	};

	
	
	/**
	 * 核心方法
	 */
	public void fill() throws Exception {
		
		
		for (SheetFiller sheetFiller : sheetFillers) {
			
			List<XSSFSheet> sheetList = new ArrayList<XSSFSheet>(); //待 填值
			
			String[] sheetNames = sheetFiller.getSheetNames(); //规定了 厚度，是下面 循环的 标准
			
			/*
			 * 设置 sheetFiller 的 sheets
			 */
			for(int i=0; i<sheetNames.length; i++) {
				
				//1、设置 rowList
				String sheetName = sheetNames[i];
				
				XSSFSheet sheet = workbook.getSheet(sheetName);
				if(sheet == null) sheet = workbook.createSheet(sheetName); /** 如果 该sheet 不存在，则 创建这个 sheet */
				sheetList.add(sheet);
				
			}
			
			XSSFSheet[] sheets = (XSSFSheet[]) sheetList.toArray(new XSSFSheet[0]);
			sheetFiller.setSheets(sheets);
			
			sheetFiller.fill();
			
		}
	}

	
	/*--------------------------------------------
    |      			getter、setter		         |
    ============================================*/
	public XSSFWorkbook getWorkbook() {
		return workbook;
	}

	public void setWorkbook(XSSFWorkbook workbook) {
		this.workbook = workbook;
	}

	public SheetFiller[] getSheetFillers() {
		return sheetFillers;
	}

	public void setSheetFillers(SheetFiller[] sheetFillers) {
		this.sheetFillers = sheetFillers;
	}
	

}
